For as long as it’s been sung, played, chanted, or clapped, music has become the one piece of nature that is uniquely human, and consistently around. Each chapter of our history sees us using music in the context of religion, entertainment, protest, and more beyond.
For the past two decades we’ve seen another of those chapters unfold. The advent of the Information Age brought with it a number of fundamental changes to our collective lifestyles and cultures, most of them coming in the form of the internet. Music wasn’t immune to this cultural tidal wave either - the anonymity of the internet, along with the ability to download, playback, and splice audio data, and new themes of cultural commentary on the untraveled new post-cyberspace society created an explosion of new genres and music styles which keep evolving at a pace unforeseen in human history.
Three such genres have had a massive impact on me, so in the name of vanity and science we’ll be looking at sample representations of these three genres: Lofi, Vaporwave , and Phonk .
Lofi music gets its name from the term low fidelity, referencing low fidelity audio - the stereo fuzz and scratchy noises some older or damaged records had on vinyl. Lofi music is the oldest of the three, finding first exposure during the late 1960’s with garage punk bands and rising to prominence during the golden era of hip hop with the proliferation of home recording hardware and software.
The music for which the term is most synonymous with now actually came alive most during the latter half of the 2010’s, resonating most with the millennial generation to the point where a hallmark of the genre now is to include audio clips of old childhood shows of that particular generation (overwhelmingly from Adult Swim and Toonami). The genre is known for a relaxed, sleepy programmed beat and a nostalgic mood.
Vaporwave is a genre that’s seen a substantial amount of metamorphosis since the 1990’s. The first genre created entirely on the internet, Vaporwave was developed largely through anonymous chat forums, a tradition that has spread to Vaporwave artists now under nonsensical or differently scripted pseudonyms. This made it a uniquely global musical movement, and it’s faced an equally global speed of evolution as well - a consistent theme of irony emerged in the early 2010’s (a reflection of disillusion with or fantasy of commercial culture involving weird pitches and strangely cut samples from advertisements other soundbites), which was promptly pushed so hard that it lost all nuance and just sounded bad. After the “Death of Vaporwave” in the late 2010’s, the genre again rose from the ashes with new themes, musical motifs, and structure.
Vaporwave as it is now is associated with dreamy synth music, with a slow, repetitive rhythm (usually on echoing drums), and comforting yet slightly eerie interjections of soundbites from popular 90’s TV shows and advertisements.
Possibly the youngest of the three genres or the oldest depending on your perspective, phonk is a child of a hip hop subgenre itself - (the aptly named) Memphis rap is a subgenre from Memphis, Tennessee with a particular style of verbal cadence and instrumentation that still shows a presence now. Here’s where the split happens. Phonk as a genre is known as a form of Memphis rap music with heavy saturation on the bass (the “dirty” bass sound), a fast-paced rhythm with kicks, hi-hats, snares, and distorted vocals. Originally these properties were a result of early splicing software and home-studio beatmakers and the low quality sound they produced, a product of a time well before the internet. However, as the Information Age took hold, the gritty and raw quality of the sound produced became a desired aesthetic, and post-internet phonk rose to prominence chasing and evolving it into a nuanced sound often paired with incongruently smooth piano or saxophone.
Phonk’s also the latest of the three to rise to mainstream prominence - that can be credited to Tiktok, which led the way to a large part of the exposure phonk has now. A style of tiktok videos showcasing cars drifting and racing used phonk as background music, and an entirely new generation discovered the style. Phonk is probably the fastest evolving genre of the three, bolstered by the increased globalization and connection of the new internet.
I’m not a purist in any of these genres, so my criteria for building samples of each went as far as accepting what Spotify says. My rationale, beyond laziness, is that Spotify curates its songs based on popularity, and for a song to show up in a selected playlist for a certain genre we can be fairly confident the song is representative of the genre to a significant degree. I ended up finding three playlists (one for each genre) curated by Spotify, and used the Spotify API by way of python and the spotipy package (a python wrapper for the API).
This data contains information about a track’s physical properties such as duration and loudness, musical properties such as key and mode, and a number of other variables detailing mood and energy. Each entry is a song from one of the 3 playlists, its corresponding dataset being said playlist.
In R, I used the tidyverse package to join the data I found for each playlist and give it a genre designation for later use.
library(tidyverse)
lofi <- read.csv('lofi.csv')
vaporwave <- read.csv('vaporwave.csv')
phonk <- read.csv('phonk.csv')
lofi <- lofi %>% mutate(genre = "lofi")
phonk <- phonk %>% mutate(genre = "phonk")
vaporwave <- vaporwave %>% mutate(genre = "vaporwave")
interim <- full_join(lofi, phonk)
all_music <- full_join(interim, vaporwave)
Here’s the resulting dataset at a glance, with selected features for viewing convenience:
library(knitr)
display <- all_music %>% select(track_name, artist, genre, tempo, duration_ms, valence)
kable(display[1:5, ], caption = 'Spotify Data')
| track_name | artist | genre | tempo | duration_ms | valence |
|---|---|---|---|---|---|
| Something Light | Guzimi | lofi | 138.012 | 125217 | 0.7520 |
| Areca | Ruth de las Plantas | lofi | 119.963 | 119741 | 0.4120 |
| Donde Estas? | Fallen Roses | lofi | 85.081 | 124245 | 0.2420 |
| Planton | Cherry Vans | lofi | 80.004 | 150000 | 0.0602 |
| Call Me | wallyPDF | lofi | 160.037 | 120022 | 0.3960 |
Here, you can see some of the various features as numerical values. All of the features as well as their scales and interpretation are explored below:
Mood
Musical Properties
Acoustic Properties
Let’s start by looking at the difference in mood between the genres. From a general standpoint, I expected phonk to have a higher level of energy and overall more active mood, with vaporwave and lofi balancing out the low to mid levels of intensity. We’ll see how valid that claim is shortly:
For data visualization, I used the R packages ggplot2 and plotly to make interactive plots that can provide a more robust picture of the distribution.
library(ggplot2)
library(plotly)
p <- ggplot(data=all_music, mapping=aes(x=danceability, fill=as.factor(genre))) + geom_density(alpha=0.75) + theme_minimal() + ggtitle('Danceability by Genre') + xlab('danceability') + ylab('frequency') + labs(fill='genre')
ggplotly(p)
p2 <- ggplot(data=all_music, mapping=aes(x=valence, fill=as.factor(genre))) + geom_density(alpha=0.75) + theme_minimal() + ggtitle('Valence by Genre') + xlab('valence') + ylab('frequency') + labs(fill='genre')
ggplotly(p2)
As far as danceability goes, it actually seems like lofi’s the most consistent - most focused around the 0.5 to 0.75 range, its distribution is much more concentrated than phonk, which lays claim to the latter side of the scale, and vaporwave, the most diverse genre out of the three in terms of danceability.
This trend continues on the density plot for valence, where it is apparent that vaporwave is almost evenly distributed throughout the entire scale of the score. Vaporwave doesn’t have a particular mood associated with it, so that makes sense. Phonk, expectedly so with the dark subject matter and instrumentation that phonk’s parent genre employs, has a decidedly negative skew whereas lofi is much more ambivalent. Lofi is light and laid back, but also deals with rather bittersweet themes such as nostalgia and heartbreak.
Both of these features focus on the instrumentation and tone of the song, but what about its speed and rhythm? To investigate that, let’s look at the features of tempo and energy:
p <- ggplot(data=all_music, mapping=aes(x=energy, fill=as.factor(genre))) + geom_density(alpha=0.75) + theme_minimal() + ggtitle('Energy Distribution by Genre') + xlab('energy') + ylab('frequency') + labs(fill='genre')
ggplotly(p)
p2 <- ggplot(data=all_music, mapping=aes(x=tempo, fill=as.factor(genre))) + geom_density(alpha=0.75) + theme_minimal() + ggtitle('Distribution of Tempo by Genre') + xlab('tempo') + ylab('frequency') + labs(fill='genre')
ggplotly(p2)
We can see that there are very clear distinctions between the genres as far as both tempo and energy go. Phonk dominates the higher portion of the energy scale, whereas lofi is starkly low energy. These are both consistent with the themes and moods of both genres. Vaporwave is somewhere in the middle, tending towards the range of 0.4 to 0.75. A running theme we can already find here is that vaporwave as a genre is far more diverse than either Lofi or Phonk. This supports the idea of Vaporwave being an eclectically built genre, as would be expected of a music style developed purely in cyberspace.
The tempo of lofi songs is decidedly lower than 100 in most cases, and phonk seems to range in between 100 and 120 BPM. As always, vaporwave spans the entire scale. Let’s take a closer look - following are some of the fastest and slowest songs in each genre.
Fastest:
all_music %>% filter(genre=='lofi') %>% filter(tempo == max(tempo)) %>% select(track_name, artist, tempo) %>% knitr::kable()
| track_name | artist | tempo |
|---|---|---|
| Phthalo Blue | Monster Rally | 201.217 |
Slowest:
all_music %>% filter(genre=='lofi') %>% filter(tempo == min(tempo)) %>% select(track_name, artist, tempo) %>% knitr::kable()
| track_name | artist | tempo |
|---|---|---|
| Bittersweet Memories | Epifania | 74.022 |
Fastest:
all_music %>% filter(genre=='phonk') %>% filter(tempo == max(tempo)) %>% select(track_name, artist, tempo) %>% knitr::kable()
| track_name | artist | tempo |
|---|---|---|
| Russia Vip | SXGXVX | 195.048 |
Slowest:
all_music %>% filter(genre=='phonk') %>% filter(tempo == min(tempo)) %>% select(track_name, artist, tempo) %>% knitr::kable()
| track_name | artist | tempo |
|---|---|---|
| ODIUM | LXST CXNTURY | 74.997 |
Fastest:
all_music %>% filter(genre=='vaporwave') %>% filter(tempo == max(tempo)) %>% select(track_name, artist, tempo) %>% knitr::kable()
| track_name | artist | tempo |
|---|---|---|
| Midnight | Hotel Pools | 196.055 |
Slowest:
all_music %>% filter(genre=='vaporwave') %>% filter(tempo == min(tempo)) %>% select(track_name, artist, tempo) %>% knitr::kable()
| track_name | artist | tempo |
|---|---|---|
| Uncanny Valley Girl | Donor Lens | 71.977 |
We can also see that even though Blue Monster Rally, the fastest lofi song in the sample is 201 BPM (which is insane), it’s on cut time, meaning every song beat is 2 beats of the tempo. This song’s true tempo would be around 100, so given more time that is something I would definitely inspect and separate.
To further understand the gist of these genres, let’s look at their musical properties.
Currently, the key value is in numbers, so I’m going to use the feature description of the variable by Spotify to translate the key numbers into key names we can understand:
## Translating number values for key into names of the keys
list_of_keys = c('C','C#','D','D#','E','F','F#','G','G#','A','A#','B')
all_music <- all_music %>% mutate(key_name = list_of_keys[key+1])
all_music %>% select(key_name) %>% unique
## key_name
## 1 C
## 2 E
## 3 G#
## 4 A#
## 5 D#
## 6 F#
## 8 B
## 12 D
## 14 F
## 17 G
## 19 C#
## 32 A
Now, let’s look at key usage across genre:
p3 <- ggplot(data=all_music, mapping=aes(x=key_name, fill=genre)) + geom_histogram(stat='count', alpha=0.75) + theme_minimal() + ggtitle('Key use by genre') + xlab('key') + labs(fill='genre')
ggplotly(p3)
Vaporwave’s favorite key:
all_music %>% filter(genre=='vaporwave') %>% group_by(key_name) %>% summarize(count=n()) %>% arrange(desc(count)) %>%
head(1) %>% knitr::kable()
| key_name | count |
|---|---|
| C# | 17 |
Lofi’s favorite key:
all_music %>% filter(genre=='lofi') %>% group_by(key_name) %>% summarize(count=n()) %>% arrange(desc(count)) %>%
head(1) %>% knitr::kable()
| key_name | count |
|---|---|
| A# | 15 |
Phonk’s favorite key:
all_music %>% filter(genre=='phonk') %>% group_by(key_name) %>% summarize(count=n()) %>% arrange(desc(count)) %>%
head(1) %>% knitr::kable()
| key_name | count |
|---|---|
| C# | 19 |
C# seems to be a general favorite with both vaporwave and phonk, whereas lofi tends to utilize the A# key more. However, they are all pretty evenly distributed - we should be able to tell more with the mode.
We will do the same thing as we did with the key column - give us another feature that shows us the name of the mode as according to Spotify:
## Creating a mode name column
all_music <- all_music %>% mutate(mode_name = ifelse(mode == 1, 'major', 'minor'))
Lofi
all_music %>% filter(genre=='lofi') %>% group_by(mode_name) %>% summarize(count=n()) %>% knitr::kable()
| mode_name | count |
|---|---|
| major | 44 |
| minor | 56 |
Vaporwave
all_music %>% filter(genre=='vaporwave') %>% group_by(mode_name) %>% summarize(count=n()) %>% knitr::kable()
| mode_name | count |
|---|---|
| major | 56 |
| minor | 44 |
Phonk
all_music %>% filter(genre=='phonk') %>% group_by(mode_name) %>% summarize(count=n()) %>% knitr::kable()
| mode_name | count |
|---|---|
| major | 62 |
| minor | 38 |
All genres excluding lofi are more likely to utilize a major mode rather than a minor mode, with phonk surprisingly more so. This is in line with lofi’s affinity for more nostalgic, bittersweet sounding music, something which minor scales are effective in representing. Phonk, though dark in nature, seems to employ more major scales, which could be explained by the fact that major scales tend to exude more energy than minor scales and artists can use sharp and flat tones within the scale to create the dissonance that minor scales naturally exhibit.
I wanted to modify the dataset to show the key and the mode name to see the favorite scale of each genre, so I do that here:
all_music <- all_music %>% mutate(key_and_mode = ifelse(mode == 0, paste(key_name, "minor", " "), paste(key_name, "major"," ")))
all_music %>% select(track_name, key_and_mode) %>% head(5)
## track_name key_and_mode
## 1 Something Light C major
## 2 Areca E major
## 3 Donde Estas? G# minor
## 4 Planton A# major
## 5 Call Me D# major
Vaporwave’s Favorite Key - Modified to show mode
all_music %>% filter(genre=='vaporwave') %>% group_by(key_and_mode) %>% unique %>% select(key_and_mode) %>% head(1) %>% knitr::kable()
| key_and_mode |
|---|
| A minor |
Lofi’s Favorite Key - Modified to show mode
all_music %>% filter(genre=='lofi') %>% group_by(key_and_mode) %>% unique %>% select(key_and_mode) %>% head(1) %>% knitr::kable()
| key_and_mode |
|---|
| C major |
Phonk’s Favorite Key - Modified to show mode
all_music %>% filter(genre=='phonk') %>% group_by(key_and_mode) %>% unique %>% select(key_and_mode) %>% head(1) %>% knitr::kable()
| key_and_mode |
|---|
| C major |
Generally, most songs tend to be in 4 beats per measure, but triple and duple timing is fairly common too. This won’t tell us too much about the properties of the songs, but it’s interesting to look at.
plot <- ggplot(data=all_music, mapping=aes(x=time_signature, fill=genre)) + geom_histogram(stat='count',alpha=0.75) + theme_minimal() + ggtitle('Time Signature use by Genre') + xlab('time signature') + ylab('frequency')
## Warning: Ignoring unknown parameters: binwidth, bins, pad
ggplotly(plot)
Unusual time signatures - 1 beat per measure
all_music %>% filter(time_signature==1) %>% select(track_name, genre, artist) %>% knitr::kable()
| track_name | genre | artist |
|---|---|---|
| MADNESS | phonk | Phonk Killer |
| Limbus | phonk | TUNDRAMANE |
| Jazz Mind ジャズ | vaporwave | Subaeris |
| Tribute to Saint Pepsi | vaporwave | Topaz Gang |
Unusual time signatures - 3 beats per measure
all_music %>% filter(time_signature==3) %>% select(track_name, genre, artist) %>% knitr::kable()
| track_name | genre | artist |
|---|---|---|
| Time For Zen | lofi | Mr Mantega |
| Flores | lofi | Bobby Dreamz BIG |
| Phthalo Blue | lofi | Monster Rally |
| Anxious | lofi | Fthmlss |
| Laguna | lofi | Bluewerks |
| rain on leaf | lofi | J. Lorenzo |
| we at pool éõéñéõ | vaporwave | VAAV Social Club |
| Hurts So Good | vaporwave | Various Artists |
| GottasaythatIneedyou | vaporwave | Persona La Ave |
| Reliving the Present Past in the Future | vaporwave | Mindspring Memories |
Possibly the most self-explanatory of all features, speechiness and instrumentalness describe the level and intensity of vocal and instrumental presence, respectively, in the track. I’d expect lofi to have a low speechiness level since it’s largely instrumental, and phonk to have the opposite, though I’m not sure how the distorted vocals would factor in. Judging on how this report’s gone by, I’m expecting vaporwave to span the plot again.
plotboi <- ggplot(data=all_music, mapping=aes(x=as.factor(genre), y=speechiness, fill=genre)) + geom_violin(alpha=0.75) + ggtitle('Speechiness by Genre') + theme_minimal() + coord_flip() + geom_jitter() + xlab('genre')
ggplotly(plotboi)
plotboi2 <- ggplot(data=all_music, mapping=aes(x=as.factor(genre), y=instrumentalness, fill=genre)) + geom_violin(alpha=0.75) + ggtitle('Instrumentalness by Genre') + theme_minimal() + coord_flip() + geom_jitter() + xlab('genre')
ggplotly(plotboi2)
So interestingly enough, there isn’t much vocal action going on in any of the genres. They both round out around the left-hand side of the plot. Though phonk seems to be more spread out, both vaporwave and lofi seem to largely be on the higher end of the instrumental scale (the first time vaporwave’s decided to pick a side on anything!). This would make sense though, as internet music in general focuses much more on instrumentation and production than would a live recording.
Loudness is kind of tricky, because it’s measured relative to the signal dampening level from Spotify’s own playback software. In general, the louder a song is, the closer to zero the marker will be, and the further down the negative the quieter the song will be, since that means the signal is being choked much further.